/**
 * @p.md
 *
 * 集群示例，演示如何使用 WASM 集群模块连接分布式 Actor 系统
 */

import { Actor } from '../../actor/actor';
import { Context } from '../../actor/context';
import { PID } from '../../actor/pid';
import { ActorSystem } from '../../actor/actorSystem';
import { Props } from '../../actor/props';
import { WasmBridge, WasmBridgeFactory } from '../wasmBridge';
import { 
  WasmClusterService, 
  WasmClusterFactory, 
  ClusterConfig, 
  MembershipEvent, 
  MembershipEventType, 
  NodeStatus 
} from '../wasmCluster';

/**
 * 客户消息
 */
interface CustomerMessage {
  customerId: string;
  content: string;
}

/**
 * 客户响应
 */
interface CustomerResponse {
  status: string;
  message: string;
}

/**
 * 客户数据
 */
interface CustomerData {
  id: string;
  name: string;
  email: string;
  orders: number;
}

/**
 * 客户 Actor
 */
class CustomerActor implements Actor {
  // 模拟数据存储
  private customerData: CustomerData;

  constructor(customerId: string) {
    // 初始化客户数据
    this.customerData = {
      id: customerId,
      name: `Customer ${customerId}`,
      email: `customer${customerId}@example.com`,
      orders: Math.floor(Math.random() * 10)
    };
  }

  receive(context: Context): void {
    const message = context.message();
    
    if (this.isCustomerMessage(message)) {
      console.log(`[CustomerActor] 收到客户消息: ${message.content} 客户ID: ${message.customerId}`);
      
      // 处理消息并回复
      const response: CustomerResponse = {
        status: 'success',
        message: `处理完成客户${this.customerData.name}的请求: ${message.content}`
      };
      
      context.respond(response);
    } else {
      console.log(`[CustomerActor] 收到未知消息类型: ${typeof message}`);
    }
  }
  
  // 类型检查辅助方法
  private isCustomerMessage(message: any): message is CustomerMessage {
    return message && typeof message === 'object' && 
      'customerId' in message && 'content' in message;
  }
}

/**
 * 客户 Actor 工厂函数
 */
function createCustomerActor(customerId: string): Actor {
  return new CustomerActor(customerId);
}

/**
 * 创建集群配置
 */
function createClusterConfig(nodeName: string, host: string, port: number): ClusterConfig {
  return {
    clusterName: 'wasm-actor-cluster',
    nodeName: nodeName,
    address: `${host}:${port}`,
    roles: ['backend'],
    seeds: [
      { host: 'localhost', port: 9001 }
    ],
    metadata: {
      region: 'eu-west',
      dataCenter: 'dc1'
    }
  };
}

/**
 * 运行集群示例
 */
export async function runClusterExample(): Promise<void> {
  console.log('启动集群示例...');
  
  try {
    // 创建 Actor 系统
    const system = new ActorSystem();
    
    // 初始化 WASM 桥接器
    const bridge = WasmBridgeFactory.getInstance();
    await bridge.initialize();
    
    // 获取集群服务
    const clusterService = WasmClusterFactory.getInstance(bridge, undefined, system);
    
    // 创建集群配置 - 生成随机端口避免冲突
    const port = 9000 + Math.floor(Math.random() * 1000);
    const config = createClusterConfig(`node-${port}`, 'localhost', port);
    
    // 初始化集群
    await clusterService.initialize(config);
    
    // 注册客户 Actor
    const customerProps = Props.fromProducer(() => {
      // 从消息中获取客户 ID 的逻辑会在 Actor 内部处理
      return new CustomerActor("default");
    });
    
    // 注册集群 Actor 类型
    clusterService.registerClusterKind('customer', customerProps);
    
    // 添加集群成员事件监听器
    const listenerId = clusterService.addMembershipListener((event: MembershipEvent) => {
      console.log(`[集群事件] 类型: ${event.eventType}, 节点: ${event.node.id}, 状态: ${event.node.status}`);
    });
    
    // 获取集群节点
    const nodes = await clusterService.getNodes();
    console.log(`集群节点数量: ${nodes.length}`);
    nodes.forEach(node => {
      console.log(`节点: ${node.id}, 地址: ${node.address}, 状态: ${node.status}`);
    });
    
    // 向客户 Actor 发送消息
    console.log('发送消息到客户 Actor...');
    for (let i = 1; i <= 3; i++) {
      const customerId = `cust-${i}`;
      const message: CustomerMessage = {
        customerId: customerId,
        content: `订单请求 #${i}`
      };
      
      try {
        // 请求并等待响应
        console.log(`请求客户 Actor ${customerId}...`);
        const response = await clusterService.requestClusterActor('customer', customerId, message);
        console.log(`收到响应: ${response.message}`);
      } catch (error) {
        console.error(`请求客户 Actor 失败: ${(error as Error).message}`);
      }
    }
    
    // 运行一段时间后关闭
    setTimeout(async () => {
      console.log('关闭集群...');
      
      // 移除监听器
      clusterService.removeMembershipListener(listenerId);
      
      // 关闭集群
      await clusterService.shutdown();
      
      console.log('集群示例运行完成。');
    }, 10000);
    
  } catch (error) {
    console.error('集群示例运行失败:', (error as Error).message);
  }
} 